package cz.zcu.fav.ratdroid.activity.calendar.reservation;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import cz.zcu.fav.ratdroid.R;
import cz.zcu.fav.ratdroid.activity.SkeletonRestListActivity;
import cz.zcu.fav.ratdroid.adapter.PeriodsCheckboxArrayAdapter;
import cz.zcu.fav.ratdroid.bean.Period;
import cz.zcu.fav.ratdroid.bean.Reservation;
import cz.zcu.fav.ratdroid.bean.Reservations;
import cz.zcu.fav.ratdroid.service.IRestListener;
import cz.zcu.fav.ratdroid.service.RestService;
import cz.zcu.fav.ratdroid.service.RestTask;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

public class ReservationPeriodsActivity extends SkeletonRestListActivity<Reservations>
{
	private Reservation reservation;
	private PeriodsCheckboxArrayAdapter adapter;
	private PeriodRunner periodRunner;
	private List<Period> loadedPeriods = new ArrayList<Period>();
	private static String SELECTED_PERIODS_KEY = "selected.periods";
	private static String LOADED_PERIODS_KEY = "loaded.periods";

	@SuppressWarnings("unchecked")
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.periodical_reservation_layout);

		HashMap<Period, Boolean> selectedResults = null;
		reservation = (Reservation) getIntent().getSerializableExtra(
				Reservation.SINGLE_RESERVATION_IDENTIFIER);

		if (savedInstanceState != null)
		{
			loadedPeriods = (List<Period>) savedInstanceState
					.getSerializable(LOADED_PERIODS_KEY);
			selectedResults = (HashMap<Period, Boolean>) savedInstanceState
					.getSerializable(SELECTED_PERIODS_KEY);
		}

		if (selectedResults == null || loadedPeriods == null)
		{
			setRestTask(RestService.getInstance().getReservation(reservation.getId(), this,
					this));
		}

		if (selectedResults != null)
		{
			adapter = new PeriodsCheckboxArrayAdapter(this, R.layout.period_row,
					loadedPeriods, selectedResults);
		} else
		{
			adapter = new PeriodsCheckboxArrayAdapter(this, R.layout.period_row,
					loadedPeriods);
		}
		setListAdapter(adapter);
	}

	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		super.onSaveInstanceState(outState);
		outState.putSerializable(LOADED_PERIODS_KEY,
				(Serializable) loadedPeriods);

		outState.putSerializable(SELECTED_PERIODS_KEY, adapter.getItems());
	}

	public boolean onCreateOptionsMenu(Menu menu)
	{
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.reservation_submit_menu, menu);
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item)
	{
		switch (item.getItemId())
		{
		case R.id.reservationSubmitButton:
			HashMap<Period, Boolean> selectedResults = adapter.getItems();

			Iterator<Entry<Period, Boolean>> iterator = selectedResults
					.entrySet().iterator();

			periodRunner = new PeriodRunner(this, iterator);
			periodRunner.start();
			return true;
		}
		return true;
	}

	@Override
	protected void onDestroy()
	{
		if (periodRunner != null)
		{
			periodRunner.stop();
		}
		super.onDestroy();
	}

	public void notifyDataLoaded(Reservations data)
	{
		super.notifyDataLoaded(data);
		adapter.notifyDataSetChanged();
		if (data != null && !data.getReservations().isEmpty())
		{
			loadedPeriods = data.getReservations().iterator().next()
					.getPeriods();
			adapter.clear();
			adapter.addAll(data.getReservations().iterator().next()
					.getPeriods());
			adapter.notifyDataSetChanged();
		}
	}

	private void notifyPeriodRunnerComplete()
	{
		runOnUiThread(new Runnable()
		{

			public void run()
			{
				Intent returnIntent = new Intent();
				setResult(RESULT_OK, returnIntent);
				finish();
			}
		});
	}

	/**
	 * Async iterator implementation
	 * 
	 * @author Lukas Gemela
	 * 
	 */
	private class PeriodRunner implements IRestListener<Reservations>
	{

		private Iterator<Entry<Period, Boolean>> iterator;
		private Context context;
		private boolean started = false;
		private RestTask<Reservations> runningTask;

		public PeriodRunner(Context context,
				Iterator<Entry<Period, Boolean>> iterator)
		{
			this.context = context;
			this.iterator = iterator;
		}

		public void stop()
		{
			runningTask.setContext(null);
		}

		public void start()
		{
			if (!started)
			{
				started = true;
				next();
			}
		}

		private void next()
		{
			while (iterator.hasNext())
			{
				Entry<Period, Boolean> entry = iterator.next();
				if (entry.getKey().isValid() != entry.getValue().booleanValue())
				{
					runningTask = RestService.getInstance().modifyPeriod(
							ReservationPeriodsActivity.this,
							entry.getKey().getId(),
							entry.getValue().booleanValue(), null, null, this);
					return;
				}
			}
			notifyPeriodRunnerComplete();
		}

		public void notifyDataLoaded(Reservations data)
		{
			if (data != null)
			{
				next();
			}
		}

		public void notifyException(final Exception ex)
		{
			runOnUiThread(new Runnable()
			{

				public void run()
				{
					Toast.makeText(context, ex.getMessage(), Toast.LENGTH_SHORT)
							.show();
				}
			});

		}

	}
}
